home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 015a / clock344.zip / IOCTL.C < prev    next >
C/C++ Source or Header  |  1993-02-07  |  17KB  |  559 lines

  1. /*****************************************************************************/
  2. /*                THE FOLLOWING PROGRAM IS THE SOLE PROPERTY OF              */
  3. /*                               RONALD Q. SMITH                             */
  4. /*             CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION           */
  5. /*                       COPYRIGHT RONALD Q. SMITH 1992                      */
  6. /*****************************************************************************/
  7.  
  8. /* Global data definitions                                                  */
  9.  
  10. #include <dos.h>
  11. #include <fcntl.h>
  12. #include <sys\types.h>
  13. #include <sys\stat.h>
  14. #include <io.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ioctl.h>
  18.  
  19. /* Function prototypes                                                      */
  20.  
  21. static int ioctl_write(void * data, int length);
  22. static int ioctl_read(void * data, int length);
  23. static int open_clock(void);
  24.  
  25. /* Global static variables                                                  */
  26.  
  27. static unsigned int handle = 0;
  28. static unsigned char password[8] = "";
  29.  
  30. /*
  31. PROCEDURE: connec
  32.  
  33. connec changes the value of the CONNECTED flag in CLOCK.SYS.  Values supported
  34. are:
  35.     0   =   disconnected
  36.     1   =   connected for writes only (default)
  37.     2   =   connected for writes and periodic reads
  38.     3   =   connected for all operations
  39.  
  40. INTERFACE:
  41.         status = connec(&connected);
  42.  
  43.             "connected" is the new value of the connected flag.
  44.  
  45.             "status" is zero if the operation succeeds.  It is the DOS
  46.             error code if the operation fails.  Likely values are:
  47.                 1   =   Not CLOCK.SYS
  48.                 5   =   Incorrect password
  49.                 6   =   Unable to obtain handle for CLOCK$
  50.                 0xD =   Illegal value for connected
  51.                 -1  =   Internal error
  52.  
  53. */
  54.  
  55. extern int pascal far connec(int *connect)
  56. {
  57.         auto struct {
  58.             int function;
  59.             int connect;
  60.         } connect_data;
  61.         auto int status;
  62.  
  63. /* Copy data to be sent to local storage.                                   */
  64.  
  65.     connect_data.function = 1;          /* Set CONNECT  */
  66.     connect_data.connect = *connect;
  67.  
  68. /* Check for legal values.                                                  */
  69.  
  70.     if (connect_data.connect > 3)
  71.         return(0xD);
  72.  
  73. /* Write new value.                                                         */
  74.  
  75.      status = ioctl_write(&connect_data, sizeof connect_data);
  76.  
  77.     return ((status == sizeof connect_data) ? 0 : ((status < 0) ?
  78.         -status : -1));
  79.  
  80. }
  81.  
  82. /*
  83. PROCEDURE: stzone
  84.  
  85. stzone sets the time zone offsets and the time zone name.
  86.  
  87. INTERFACE:
  88.         status = stzone(&hour, &minute, &second, zone);
  89.  
  90.             "hour:minute:second" is the difference in time between UTC and
  91.             local time.  The values are positive West of Greenwich and
  92.             negative East.
  93.  
  94.             "zone" is a character string containing the local time zone name.
  95.             It must be LJSF (Left Justified, Space Filled) or LJNT (Left
  96.             Justified, NULL Terminated).  It must be no more than 32
  97.             characters in length.
  98.  
  99.             "status" is zero if the operation succeeds.  It is the DOS
  100.             error code if the operation fails.  Likely values are:
  101.                 1   =   Not CLOCK.SYS
  102.                 5   =   Incorrect password
  103.                 6   =   Unable to obtain handle for CLOCK$
  104.                 0xD =   Illegal value for offset
  105.                 -1  =   Internal error
  106. */
  107.  
  108. extern int pascal far stzone(int *std_hour, int *std_minute, int *std_second,
  109.     unsigned char std_name[32], int *day_hour, int *day_minute,
  110.     int *day_second, unsigned char day_name[32])
  111.  
  112. {
  113.     auto struct {
  114.         int function;
  115.         struct time_zone standard;
  116.         struct time_zone daylight;
  117.     } zone_data;
  118.     auto int status;
  119.     auto char *zone_loc;
  120.  
  121. /* Copy values to local storage.  LJSF zones.                               */
  122.  
  123.     zone_data.function = 2;
  124.  
  125.     zone_data.standard.offs.hour = *std_hour;
  126.     zone_data.standard.offs.minute = *std_minute;
  127.     zone_data.standard.offs.second = *std_second;
  128.     memcpy(zone_data.standard.zone, std_name, sizeof zone_data.standard.zone);
  129.  
  130.     zone_data.daylight.offs.hour = *day_hour;
  131.     zone_data.daylight.offs.minute = *day_minute;
  132.     zone_data.daylight.offs.second = *day_second;
  133.     memcpy(zone_data.daylight.zone, day_name, sizeof zone_data.daylight.zone);
  134.  
  135. /* Check for legal offset values.                                           */
  136.  
  137.     if ((abs(zone_data.standard.offs.hour) > 23) ||
  138.         (abs(zone_data.standard.offs.minute) > 59) ||
  139.         (abs(zone_data.standard.offs.second) > 59) ||
  140.         (abs(zone_data.daylight.offs.hour) > 23) ||
  141.         (abs(zone_data.daylight.offs.minute) > 59) ||
  142.         (abs(zone_data.daylight.offs.second) > 59))
  143.     {
  144.         return(0xD);
  145.     }
  146.  
  147. /* Write new values to CLOCK.SYS                                            */
  148.  
  149.     status = ioctl_write(&zone_data, sizeof zone_data);
  150.  
  151.     return ((status == sizeof zone_data) ? 0 : ((status < 0) ?
  152.         -status : -1));
  153.  
  154. }
  155.  
  156. /*
  157. PROCEDURE: stmode
  158.  
  159. stmode sets a new value for the mode flag.
  160.  
  161. INTERFACE:
  162.         status = stmode(&mode);
  163.  
  164.             "mode" is the new value for the mode flag.  The "mode" flag
  165.             contains a set of bits which may be set in any combination.
  166.  
  167.             "status" is zero if the operation succeeds.  It is the DOS
  168.             error code if the operation fails.  Likely values are:
  169.                 1   =   Not CLOCK.SYS
  170.                 5   =   Incorrect password
  171.                 6   =   Unable to obtain handle for CLOCK$
  172.                 0xD =   Illegal value for mode
  173.                 -1  =   Internal error
  174. */
  175.  
  176. extern int pascal far stmode(struct modes *mode)
  177.  
  178. {
  179.     auto struct {
  180.         int function;
  181.         struct modes mode;
  182.     } mode_data;
  183.     auto int status;
  184.  
  185. /* Copy values to local storage.                                            */
  186.  
  187.     mode_data.function = 3;
  188.     mode_data.mode = *mode;
  189.  
  190. /* Write new value to CLOCK.SYS                                             */
  191.  
  192.     status = ioctl_write(&mode_data, sizeof mode_data);
  193.  
  194.     return ((status == sizeof mode_data) ? 0 : ((status < 0) ?
  195.         -status : -1));
  196.  
  197. }
  198.  
  199. /*
  200. PROCEDURE: rstrct
  201.  
  202. rstrct sets the time restriction limit values.
  203.  
  204. INTERFACE:
  205.         status = rstrct(&back_hour, &back_minute, &back_second, &forward_hour,
  206.             &forward_minute, &forward_second);
  207.  
  208.             "back_hour:back_minute:back_second" is the new limit on backward
  209.             time changes.  All values must be positive and less than or
  210.             equal to 23:59:59.
  211.  
  212.             "forward_hour:forward_minute:forward_second" is the new limit on
  213.             forward time changes.  All values must be positive and less than
  214.             or equal to 23:59:59.
  215.  
  216.             "status" is zero if the operation succeeds.  It is the DOS
  217.             error code if the operation fails.  Likely values are:
  218.                 1   =   Not CLOCK.SYS
  219.                 5   =   Incorrect password
  220.                 6   =   Unable to obtain handle for CLOCK$
  221.                 0xD =   Illegal value for limits
  222.                 -1  =   Internal error
  223. */
  224.  
  225. extern int pascal far rstrct(int *back_hour, int *back_minute,
  226.     int *back_second, int *forward_hour, int *forward_minute,
  227.     int *forward_second)
  228.  
  229. {
  230.     auto struct {
  231.         int function;
  232.         int back_hour;
  233.         int back_minute;
  234.         int back_second;
  235.         int forward_hour;
  236.         int forward_minute;
  237.         int forward_second;
  238.     } rstrct_data;
  239.     auto int status;
  240.  
  241. /* Copy values to local storage.                                            */
  242.  
  243.     rstrct_data.function = 4;
  244.     rstrct_data.back_hour = *back_hour;
  245.     rstrct_data.back_minute = *back_minute;
  246.     rstrct_data.back_second = *back_second;
  247.     rstrct_data.forward_hour = *forward_hour;
  248.     rstrct_data.forward_minute = *forward_minute;
  249.     rstrct_data.forward_second = *forward_second;
  250.  
  251. /* Check values for legal limits.                                           */
  252.  
  253.     if ((rstrct_data.back_hour < 0) || (rstrct_data.back_hour > 23) ||
  254.         (rstrct_data.back_minute < 0) || (rstrct_data.back_minute > 59) ||
  255.         (rstrct_data.back_second < 0) || (rstrct_data.back_second > 59) ||
  256.         (rstrct_data.forward_hour < 0) || (rstrct_data.forward_hour > 23) ||
  257.         (rstrct_data.forward_minute < 0) || (rstrct_data.forward_minute > 59)
  258.         || (rstrct_data.forward_second < 0) ||
  259.         (rstrct_data.forward_second > 59))
  260.     {
  261.         return(0xD);
  262.     }
  263.  
  264. /* Write new values to CLOCK.SYS                                            */
  265.  
  266.     status = ioctl_write(&rstrct_data, sizeof rstrct_data);
  267.  
  268.     return ((status == sizeof rstrct_data) ? 0 : ((status < 0) ?
  269.         -status : -1));
  270.  
  271. }
  272.  
  273. /*
  274. PROCEDURE: tdisp
  275.  
  276. tdisp sets the time display cursor location.  The mode to enable the display
  277. must be set separately with stmode.
  278.  
  279. INTERFACE:
  280.         status = tdisp(&disp_x, &disp_y, &attribute);
  281.  
  282.             "disp_x" is the screen x coordinate in character positions of
  283.             the left-most character of the time display.  The value must be
  284.             positive and less than 256.
  285.  
  286.             "disp_y" is the screen y coordinate in lines of the time display.
  287.             The value must be positive and less than 256.
  288.  
  289.             "attribute" is the screen attribute to be used for the display.
  290.             The value must be less than 256 and the low-order three bits of
  291.             each nybble must not be equal.
  292.  
  293.             "status" is zero if the operation succeeds.  It is the DOS
  294.             error code if the operation fails.  Likely values are:
  295.                 1   =   Not CLOCK.SYS
  296.                 5   =   Incorrect password
  297.                 6   =   Unable to obtain handle for CLOCK$
  298.                 0xD =   Illegal value for tdisp
  299.                 -1  =   Internal error
  300. */
  301. extern int pascal far tdisp(int *disp_x, int *disp_y, int *attribute)
  302.  
  303. {
  304.  
  305.     auto struct {
  306.         int function;
  307.         int disp_x;
  308.         int disp_y;
  309.         int attribute;
  310.     } tdisp_data;
  311.     auto int status;
  312.  
  313. /* Copy values to local storage.                                            */
  314.  
  315.     tdisp_data.function = 5;
  316.     tdisp_data.disp_x = *disp_x;
  317.     tdisp_data.disp_y = *disp_y;
  318.     tdisp_data.attribute = *attribute;
  319.  
  320. /* Check values for ranges.                                                 */
  321.  
  322.     if ((tdisp_data.disp_x < 0) || (tdisp_data.disp_x > 255) ||
  323.         (tdisp_data.disp_y < 0) || (tdisp_data.disp_y > 255) ||
  324.         (tdisp_data.attribute < 0) || (tdisp_data.attribute > 255) ||
  325.         ((tdisp_data.attribute & 7) == ((tdisp_data.attribute >> 4) & 7)))
  326.     {
  327.         return(0xD);
  328.     }
  329.  
  330. /* Write new values to CLOCK.SYS                                            */
  331.  
  332.     status = ioctl_write(&tdisp_data, sizeof tdisp_data);
  333.  
  334.     return ((status == sizeof tdisp_data) ? 0 : ((status < 0) ?
  335.         -status : -1));
  336.  
  337. }
  338.  
  339. /*
  340. PROCEDURE: setpw
  341.  
  342. setpw sets the password to be used on all future operations to change the
  343. CLOCK.SYS values.  setpw must be called with the correct password prior to
  344. any operation after password checking is enabled.  If password checking is
  345. not enabled, setpw is not required.
  346.  
  347. INTERFACE:
  348.  
  349.         setpw(pword);
  350.  
  351.             "pword" is an 8-character array containing the password to
  352.             be used.  It must be LJSF or LJNF (Left Justified, NULL Filled).
  353.  
  354. */
  355.  
  356. extern void pascal far setpw(unsigned char *pword)
  357.  
  358. {
  359.  
  360. /* Copy the password to local storage for use on later calls.               */
  361.  
  362.     memcpy(password, pword, sizeof password);
  363.  
  364. }
  365.  
  366. /*
  367. PROCEDURE: newpw
  368.  
  369. newpw sets a new password into CLOCK.SYS.  This new password is immediately
  370. effective.  newpw also copies the new password to local storage as the current
  371. password if the operation of setting it in CLOCK.SYS is successful.
  372.  
  373. INTERFACE:
  374.  
  375.         status = newpw(pword);
  376.  
  377.             "pword" is the new password.  It must be exactly 8 characters in
  378.             length.  It may be LJSF or LJNF.
  379.  
  380.             "status" is zero if the operation succeeds.  It is the DOS
  381.             error code if the operation fails.  Likely values are:
  382.                 1   =   Not CLOCK.SYS
  383.                 5   =   Incorrect password
  384.                 6   =   Unable to obtain handle for CLOCK$
  385.                 -1  =   Internal error
  386. */
  387.  
  388. extern int pascal far newpw(unsigned char *pword)
  389.  
  390. {
  391.  
  392.     auto struct {
  393.         int function;
  394.         unsigned char pword[sizeof password];
  395.     } newpw_data;
  396.     auto int status;
  397.  
  398. /* Copy the values to local storage.                                        */
  399.  
  400.     newpw_data.function = 6;
  401.     memcpy(newpw_data.pword, pword, sizeof password);
  402.  
  403. /* Set the new password in CLOCK.SYS                                        */
  404.  
  405.     status = ioctl_write(&newpw_data, sizeof newpw_data);
  406.  
  407. /* If everything OK, copy the new password to the current password.         */
  408.  
  409.     if (status == sizeof newpw_data)
  410.     {
  411.         memcpy(password, pword, sizeof password);
  412.         return(0);
  413.     }
  414.  
  415.     return ((status < 0) ? -status : -1);
  416.  
  417. }
  418.  
  419.  
  420. /*
  421. PROCEDURE: clksta
  422.  
  423. clksta gets the current state of CLOCK.SYS.
  424.  
  425. INTERFACE:
  426.         status = clksta(&data);
  427.  
  428.         "data" is a structure that will contain the returned information.
  429.  
  430.         "status" is the number of bytes read or the negative of the DOS
  431.         error status if an error occurs.
  432.  
  433. */
  434.  
  435. extern int pascal far clksta(struct CLOCK_DATA *data)
  436.  
  437. {
  438.  
  439.     return(ioctl_read(data, sizeof (struct CLOCK_DATA)));
  440.  
  441. }
  442.  
  443. /****************************************************************************/
  444. /*                       INTERNAL FUNCTIONS                                 */
  445. /****************************************************************************/
  446.  
  447. /*
  448. PROCEDURE: ioctl_write
  449.  
  450. ioctl_write performs a "Send Control Data to Character Device" function.
  451.  
  452. INTERFACE:
  453.     status = ioctl_write(data, length);
  454.  
  455.         "data" is an array of "length" bytes.
  456.  
  457.         "length" is the number of bytes to be sent.
  458.  
  459.         "status" is the number of bytes accepted by the device or the negative
  460.         of _doserrno if an error occurs.
  461.  
  462. */
  463.  
  464. static int ioctl_write(void * data, int length)
  465.  
  466. {
  467.         auto union REGS regs;
  468.         auto unsigned char send_data[200];  /* Leave room for growth    */
  469.  
  470. /* If file for CLOCK$ not open, open it.                                    */
  471.  
  472.     if (!handle)
  473.     {
  474.         if (open_clock() <= 0)
  475.             return(-_doserrno);
  476.     }
  477.  
  478. /* Copy password and caller's data to same area to send.                    */
  479.  
  480.     memcpy(send_data, password, sizeof password);
  481.     memcpy(&send_data[sizeof password], data, length);
  482.  
  483.     regs.x.ax = 0x4403;             /* IOCTL Send Control Data  */
  484.     regs.x.bx = handle;
  485.     regs.x.cx = length + sizeof password;
  486.     regs.x.dx = (int) send_data;    /* Send data bytes  */
  487.  
  488.     intdos(®s, ®s);
  489.  
  490.     return(regs.x.cflag ? -_doserrno : regs.x.ax - sizeof password);
  491. }
  492.  
  493.  
  494. /*
  495. PROCEDURE: ioctl_read
  496.  
  497. ioctl_read performs a "Read Control Data from Character Device" function.
  498.  
  499. INTERFACE:
  500.     status = ioctl_read(data, length);
  501.  
  502.         "data" is an array of "length" bytes to receive the information.
  503.  
  504.         "length" is the number of bytes to be read.
  505.  
  506.         "status" is the number of bytes returned by the device or
  507.         is the negative of the DOS error status if an error occurs.
  508.  
  509. */
  510.  
  511. static int ioctl_read(void * data, int length)
  512.  
  513. {
  514.         auto union REGS regs;
  515.  
  516. /* If file for CLOCK$ not open, open it.                                    */
  517.  
  518.     if (!handle)
  519.     {
  520.         if (open_clock() <= 0)
  521.             return(-_doserrno);
  522.     }
  523.  
  524.     regs.x.ax = 0x4402;             /* IOCTL Read Control Data  */
  525.     regs.x.bx = handle;
  526.     regs.x.cx = length;
  527.     regs.x.dx = (int) data;         /* Read data bytes  */
  528.  
  529.     intdos(®s, ®s);
  530.  
  531.     return(regs.x.cflag ? -_doserrno : regs.x.ax);
  532.  
  533. }
  534.  
  535. /*
  536. PROCEDURE: open_clock
  537.  
  538. "open_clock" opens a file handle for the CLOCK$ device.
  539.  
  540. INTERFACE:
  541.         open_clock();
  542.  
  543.                    open_clock returns the file handle or the value -1 if
  544.                    unable to establish a handle.
  545. */
  546.  
  547. static int open_clock(void)
  548.  
  549. {
  550.         return(handle = open("CLOCK$",O_RDWR));
  551. }
  552.  
  553. /*****************************************************************************/
  554. /*                THE PRECEDING PROGRAM IS THE SOLE PROPERTY OF              */
  555. /*                               RONALD Q. SMITH                             */
  556. /*             CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION           */
  557. /*                       COPYRIGHT RONALD Q. SMITH 1992                      */
  558. /*****************************************************************************/
  559.